home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************************
- *
- *
- * MacZapp -- a standard Mac application template
- *
- *
- *************************************************************************************************/
-
- /* This is a comment- comments are delimited by slash-star to start and star-slash to end: */
- // alternatively, a comment on a single line can start with two slashes- it doesn't need
- // to be terminated, but each line needs the comment delimiter if you use this style.
-
- // The first line of actual code should include any header files that this code requires. The
- // toolbox headers "MacHeaders" are automatically included by THINK C, etc. Note that any
- // statement beginning with # is a COMPILER DIRECTIVE- it is an instruction to the compiler, not
- // to the computer.
-
- // This line includes a header file which has the function prototypes. These are needed so that
- // the compiler can tell what parameters to pass to functions, and to chack the syntax of function
- // calls
-
-
- #include "Prototypes.h"
- #include "Palettes.h"
- #include "Gestalt.h"
- #include "ShowHideMenubar.h"
-
- //#include "DialogUtils.h"
-
- //#include "NewSneakyJump.c"
- //#include "CoolSliderCDEF.h"
-
-
- // you can declare a constant byy using the #define statement. This works like Pascal's CONST
- // keyword. It is good style to use symbolic constants wherever possible rather than hard coding
- // numerical values- it makes the code easier to understand (by a human!). Furthermore, a good
- // convention is to begin all constants with the letter k, all globals with the letter g, to
- // use names starting with a lowercase letter for local variables, and names starting with an
- // uppercase letter for function names. This is only a convention- you don't HAVE to do this, but
- // if you are consistent, you'll find it much easier to write readable code.
-
- #define kSleepTime 10 // number of ticks to give up to background programs
- #define kUntitledWindowID 128 // resource ID of the main window template
- #define kMenuBarID 128 // resource ID of the MBAR resource
- #define kAppleMenuID 128 // ID of the apple menu
-
- // a note about resources. In THINK C and similar, if you create a ResEdit file which has the
- // same name as the PROJECT, appended with .rsrc, this file will automatically opened when you
- // run the application in the development environment. This file must be in the same folder as
- // the project file. You can put all your resources in this file- the compiler will copy them
- // into the application when you finally build it
-
- // next, declare any global variables you want. This is like pascals VAR statement, except that C
- // understands that any name left 'naked' is a variable by default
-
- Boolean gDone; // if you set this to TRUE, the app will quit
- short gSleepTime; // this is the current number of sleep ticks
- FSSpec gSlideFolder; // the filespec for the source image folder
- Boolean gFolderChosen; // true if a folder has been selected
- WindowPtr gSlideWindow; // the window to display them in
- MenuHandle gFileMenu;
-
- extern long gSlideTicks;
- extern long gLastTicks;
- extern short gSlideIndex;
- extern short gSlidePhase;
- extern PicHandle gPicture;
- extern Boolean gHideMBar;
- extern Boolean gAutoRun;
-
- // now for the code! Evey C program must have one and only one entry point, called main. Here
- // it is:
-
- void main()
- {
- // this is the main program, in its entirety:
-
- InitialiseTheApp();
- RunTheApp();
- QuitTheApp();
- }
-
- // the form of a function is always the same. There is no distinction between FUNCTIONS and
- // PROCEDURES, as there is in Pascal. Everything is a function, though by using the VOID keyword,
- // is can return nothing, and so is equivalent to a procedure. Every function must have a
- // parameter list, though this may be empty. i.e. AFunction() is valid, AFunction is not. (it must
- // have brackets following the name).
-
- // There is no BEGIN and END statement, instead, the { and } brackets serve the same function.
- // all program statements must be terminated by a semi-colon.
-
- // here are the procedures that main calls:
-
- void InitialiseTheApp()
- {
- // normally you would put a comment here explaining what the function does. This one starts
- // up the application, installing the menubar and opening the untitled window
-
- Handle theMenuBar;
- MenuHandle theAppleMenu;
-
- // every mac application starts up with the same 'mantra' which must be chanted exactly as
- // given here to persuade the mac spirits to smile favourably on your program...
-
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- InitMenus();
- TEInit();
- InitDialogs(NULL);
-
- // now you should clear out the event queue in case any stray clicks or keypresses are left
- // there
-
- FlushEvents(everyEvent,0);
-
- // now give yourself enough memory. For a bigger app, you may need to call MoreMasters a few
- // more times
-
- MaxApplZone();
- MoreMasters();
-
- // see if the program can run on this Mac- if not, we show an alert and exit
-
- CheckCanRun();
-
- // now we can install our menu bar. We use an MBAR resource to list the actual menus. This
- // makes it easier to add menus just by editing the resources.
-
- theMenuBar = GetNewMBar(kMenuBarID);
-
- if(theMenuBar)
- {
- SetMenuBar(theMenuBar);
- ReleaseResource(theMenuBar);
-
- // now fill the apple menu with a list of all the apple menu items. This is done as
- // follows. This appears a bit odd, once you know what this means, but the reasons
- // for it have to do with the way System 1 worked, so just take my word for it...
-
- theAppleMenu = GetMHandle(kAppleMenuID);
-
- if (theAppleMenu)
- AddResMenu(theAppleMenu,'DRVR');
- }
-
- gFileMenu = GetMHandle(kFileMenu);
-
- // OK, we have installed the menu bar, now we draw it, which displays the titles
-
- DrawMenuBar();
-
- // set up the application globals
-
- gDone = FALSE; // we're not quitting yet
- gSleepTime = kSleepTime; // set the sleep period
-
- InitCursor(); // set the cursor to the arrow and make it visible
-
-
- gSlideTicks = 300; // 5 seconds, but overriden by prefs
- gLastTicks = TickCount();
- gSlideIndex = 0;
- gFolderChosen = FALSE;
- gSlidePhase = 0;
-
- // ready to go, so open a default window
-
- RestorePrefs();
- OpenNewWindow(kUntitledWindowID);
- if (gFolderChosen && gAutoRun)
- StartSlideshow();
- else
- StopSlideshow();
- }
-
-
-
- void RunTheApp()
- {
- // this function loops round, pulling events off the queue as long as the user hasn't quit.
- // The events arrive in any order, and the app just handles them one after another
-
- EventRecord theEvent; // this record is the current event
-
- while (! gDone)
- {
- if (WaitNextEvent(everyEvent,&theEvent,gSleepTime,NULL))
- {
- // we obtained an event, now handle it
-
- HandleTheEvent(&theEvent);
- }
- else
- RunSlideshow(); // show the slides while null events arrive
- }
- }
-
-
- void QuitTheApp()
- {
- // here you would do any cleanup during the quitting phase of the application. In this case
- // we do nothing, so this is an empty function or "stub"
-
- SetMBarState(SHOW);
- RestoreDeviceClut(NULL);
- SavePrefs();
- }
-
-
- // The next most important function is the event handler. This determines the type of event that
- // occurred, and dispatches it to the various routines needed to process them
-
- void HandleTheEvent(EventRecord *theEvent)
- {
- WindowPtr targWindow; // the window the event was aimed at
- char keyChar; // the ascii code of a key that was pressed
- long mSelect; // menu and item chosen, if any
-
- switch (theEvent->what)
- {
- case mouseDown:
- // the mouse was clicked somewhere- pass it on
- HandleMouseEvent(theEvent);
- break;
- case updateEvt:
- // a window needs refreshing, find out which and do it
-
- targWindow = (WindowPtr) theEvent->message;
- SetPort(targWindow);
- BeginUpdate(targWindow);
-
- // an update event is telling us to refresh the window, so we call our
- // drawing function for the window
-
- DrawTheWindow(targWindow);
- EndUpdate(targWindow);
- break;
- case keyDown:
- // a key was pressed on the keyboard, if it was together with the command key,
- // then it is considered as a menu key shortcut, so look it up and dispatch it
- // as if the selection came from the menu in the first place
-
- keyChar = theEvent->message & charCodeMask;
- if ((theEvent->modifiers & cmdKey) == cmdKey)
- {
- mSelect = MenuKey(keyChar);
- HandleMenuSelection(mSelect);
- }
- else
- HandleKeypress(FrontWindow(),keyChar);
- break;
- case autoKey:
- // a key is held down on the keyboard. This shouldn't be a menu command, so just pass
- // it on
-
- keyChar = theEvent->message & charCodeMask;
- HandleKeypress(FrontWindow(),keyChar);
- break;
- case osEvt:
- case activateEvt:
- case diskEvt:
- default:
- // other event types are ignored in this simple example
- break;
- }
- }
-
-
- #define kMinWindowWidth 60
- #define kMinWindowHeight 40
-
-
- void HandleMouseEvent(EventRecord *theEvent)
- {
- // the mouse went down somewhere. This function finds out where and dispatches that click to
- // the appropriate place
-
- short mouseTarget; // a code for what the mouse actually hit
- WindowPtr targWindow; // if it clicked in a window, this is the one
- Rect dragBounds,growBounds; // rectangles for controlling window drags etc.
- long mSelect; // menu info if a menu was pulled down
- long growthFactor; // new size of a window after a grow
-
- // in case we're going to do a window drag, set up the rect for constraining it
-
- dragBounds = (*GetGrayRgn())->rgnBBox;
- InsetRect(&dragBounds,4,4);
-
- // determine which part of the screen was clicked
-
- mouseTarget = FindWindow(theEvent->where,&targWindow);
-
- switch (mouseTarget)
- {
- case inMenuBar:
- // mouse was clicked in the menubar- pull down the menu and track it
-
- mSelect = MenuSelect(theEvent->where);
- HandleMenuSelection(mSelect);
- break;
- case inDrag:
- // the mouse is in drag (dressed as a woman) so move the window
-
- DragWindow(targWindow,theEvent->where,&dragBounds);
- break;
- case inGrow:
- // the mouse is in the grow box of a resizeable window, so drag the outline and
- // resize the window if the user wants that. growBounds constrains the size
- // to a certain largest and certain smallest size
-
- SetRect(&growBounds,kMinWindowWidth,kMinWindowHeight,dragBounds.right,dragBounds.bottom);
-
- growthFactor = GrowWindow(targWindow,theEvent->where,&growBounds);
- if (growthFactor)
- SizeWindow(targWindow,LoWord(growthFactor),HiWord(growthFactor),TRUE);
-
- break;
- case inGoAway:
- // the mouse was clicked in the close box of a window- track it and if the user actually
- // clicked it, then get rid of the window altogether
-
- if (TrackGoAway(targWindow,theEvent->where))
- DisposeWindow(targWindow);
-
- break;
- case inZoomIn:
- case inZoomOut:
- // the mouse was clicked in the zoom box of a zoomable window- track it, and then zoom the
- // window appropriately
-
- if (TrackBox(targWindow,theEvent->where,mouseTarget))
- {
- SetPort(targWindow);
- EraseRect(&targWindow->portRect);
- ZoomWindow(targWindow,mouseTarget,TRUE);
- }
- break;
- case inSysWindow:
- // the mouse was clicked in a desk accessory window- just pass it to the system to deal with
- SystemClick(theEvent,targWindow);
- break;
- case inContent:
- // the mouse was clicked in the main area of the users window. If the window is not in front, then
- // it should be brought to the front. If it is already in front, pass the click to the window
-
- if (targWindow == FrontWindow())
- ClickTheWindow(targWindow,theEvent->where);
- else
- SelectWindow(targWindow);
-
- break;
- default:
- break;
- }
- }
-
-
- //#define kFileMenu 129
- #define kEditMenu 130
- #define kShowAboutBox 1
- #define kAboutBoxID 128
-
-
- void HandleMenuSelection(long mSelect)
- {
- // this function dispatches chosen menu commands. Only the very basic ones are handled here- you will need
- // to extend this function to implement other menu commands. The defines above indicate the menu layout
- // that is understood by this function.
-
- short menuID,itemID;
- Str255 daName;
- GrafPtr savePort;
- short itemClicked;
-
- menuID = HiWord(mSelect);
- itemID = LoWord(mSelect);
-
- switch(menuID)
- {
- case kAppleMenuID:
- if (itemID == kShowAboutBox)
- //itemClicked = Alert(kAboutBoxID,NULL);
- DoAboutBox();
- else
- {
- // a DA was chosen, so open it
-
- GetItem(GetMHandle(menuID),itemID,daName);
- GetPort(&savePort);
- OpenDeskAcc(daName);
- SetPort(savePort);
- }
- break;
- case kFileMenu:
- switch (itemID)
- {
- case kItemChooseSlides:
- gFolderChosen |= ChooseFolder(&gSlideFolder);
- if (gFolderChosen)
- StopSlideshow();;
- break;
- case kItemOptions:
- DoOptions();
- break;
- case kItemGo:
- StartSlideshow();
- break;
- case kItemStop:
- StopSlideshow();
- break;
- case kItemStartOver:
- ResetSlideshow();
- break;
- case kItemQuit:
- gDone = TRUE;
- break;
- default:
- SysBeep(1);
- break;
- }
- break;
- case kEditMenu:
- break;
- default:
- break;
- }
- HiliteMenu(0);
- }
-
-
- void OpenNewWindow(short windowResID)
- {
- // opens and displays a window using a WIND resource with the given ID
-
- WindowPtr theWindow;
- Rect bounds;
-
- theWindow = GetNewCWindow(windowResID,NULL,(WindowPtr) -1L);
-
- if (theWindow)
- {
- SetSlideWindowSize(theWindow);
- ShowWindow(theWindow);
- SelectWindow(theWindow);
-
- gSlideWindow = theWindow;
- }
- }
-
-
- void ClickTheWindow(WindowPtr theWindow,Point clickLocation)
- {
- // this handles clicks for the users window. This is mostly an empty function- you will need to
- // modify it to make it do anything useful
-
- GrafPtr savePort;
- short partCode,val;
- ControlHandle aControl;
-
- if (theWindow)
- {
- GetPort(&savePort);
- SetPort(theWindow);
-
- // translate coordinates from global to window local
-
- GlobalToLocal(&clickLocation);
- SetPort(savePort);
-
- // in this application, we allow mouse clicks to suspend slideshow
- // display temporarily (i.e. hold image function). This is
- // simply accomplished by waiting here for the mouse button to go up.
-
- while (WaitMouseUp());
- }
- }
-
-
- void HandleKeypress(WindowPtr theWindow,char keyChar)
- {
- // handles keystrokes targeted at this window. This does nothing at all at present
- }
-
-
- /******************************************************************************
- CopyPString
-
- Copy a Pascal string
- ******************************************************************************/
-
- void CopyPString(
- ConstStr255Param srcString,
- Str255 destString)
- {
- BlockMove(srcString, destString, srcString[0] + 1L);
- }
-
-
- /******************************************************************************
- ConcatPStrings
-
- Concatenate two Pascal strings by attaching the second string on
- the end of the first string.
- ******************************************************************************/
-
- void ConcatPStrings(
- Str255 first,
- ConstStr255Param second)
- {
-
- short charsToCopy;
-
- // Truncate if concatenated string would be longer than 255 chars.
-
- charsToCopy = Min(second[0], 255 - first[0]);
- BlockMove(second + 1, first + first[0] + 1, (long) charsToCopy);
- first[0] += charsToCopy;
- }
-
-
-
- void CheckCanRun()
- {
- OSErr theErr;
- long gestaltResult;
- Boolean mustQuit = FALSE;
-
- theErr = Gestalt(gestaltQuickdrawVersion,&gestaltResult);
-
- if (theErr || gestaltResult < gestalt32BitQD)
- mustQuit = TRUE;
-
- theErr = Gestalt(gestaltProcessorType,&gestaltResult);
-
- if (theErr || gestaltResult < gestaltCPU68020)
- mustQuit = TRUE;
-
- theErr = Gestalt(gestaltSystemVersion,&gestaltResult);
-
- if (theErr || gestaltResult < 0x0700)
- mustQuit = TRUE;
-
- if (mustQuit)
- {
- Alert(131,NULL);
- ExitToShell();
- }
- }
-